<?php
namespace myuphp\Common;
/**
* Class Tpl 模板引擎
*/
class Tpl 
{
    protected $view_dir;
    //模板文件
    protected $cache_dir;
    //缓存文件
    protected $lifetime;
    //过期时间
    protected $vars = [];
    //存放显示变量的数组
    /**
     * Tpl constructor.
     * @param string $view_dir
     * @param string $cache_dir
     * @param string $lifetime
     */
    public function __construct($view_dir = '', $cache_dir = '', $lifetime = '')
    {
        //如果模板文件不为空，则设置，为空则为默认值
        if (!empty($view_dir)) {
            if ($this->check_dir($view_dir)) {
                $this->view_dir = $view_dir;
            }
        }
        //如果缓存文件不为空，则设置，为空时为默认值
        if (!empty($cache_dir)) {
            if ($this->check_dir($cache_dir)) {
                $this->cache_dir = $cache_dir;
            }
        }
        //如果过期时间不为空，则设置，为空时为默认值
        if (!empty($lifetime)) {
            $this->lifetime = $lifetime;
        }
    }
    /**
     * 
     * 对外公开的方法
     * @param string $name
     * @param string $value
     */
    public function assign($name, $value)
    {
        $this->vars[$name] = $value;
        //将传入的参数以键值对存入数组中
    }
    /**
     * 测试文件
     * @param $dir_path
     * @return bool
     */
    protected function check_dir($dir_path)
    {
        //如果文件不存在或不是文件夹，则创建
        if (!file_exists($dir_path) || !is_dir($dir_path)) {
            return mkdir($dir_path, 0777, true);
        }
        //如果文件不可读或不可写，则设置模式
        if (!is_writable($dir_path) || !is_readable($dir_path)) {
            return chmod($dir_path, 0777);
        }
        return true;
    }
    /**
     * 分页显示
     * $data数据
     */
    protected function page($data)
    {
    	$count = $data['count'];//记录总条数
		@$page_size = $data['show'];//每页显示条数
		@$page_all = ceil($count / $page_size);//总页数
		@($page = $_GET['page'] ? $_GET['page'] : 1);//当前页数
		@$page_up = $page - 1 > 1 ? $page - 1 : 1;//上一页
		@$page_next = $page + 1 > $page_all ? $page_all : $page + 1;//下一页
		@$key = ($page - 1) * $page_size;
		if (empty(strpos(curPageURL(), '?'))) {
		    $url = curPageURL() . '/?page';
		} else {
		    if (empty($_GET['page'])) {
		        $url = curPageURL() . '&page';
		    } else {
		        $url = preg_replace("/page(.*)/is", "page", curPageURL());
		    }
		}
		if ($count==0) {
			return;
		}
		if ($page_all!=1&&!empty($data)) {
			echo "<div align='center' class='page'><a \r\n\r\nhref='" . $url . "=1'>首页 </a><a href='" . $url . "=\r\n\r\n{$page_up}'> 上一页 </a><a href='" . $url . "={$page_next}\r\n\r\n'> 下一页 </a><a \r\n\r\nhref='" . $url . "={$page_all}'>尾页</a><span> 第 {$page}/{$page_all}页 </span>";
		} 
         
    }
    /**
     * 展示方法
     * @param $view_name
     * @param bool $isInclude
     * @param null $uri
     */
    public function view($view_name='', $isInclude = true, $uri = null)
    {
        //通过传入的文件名，得到模板文件路径
        if (empty($view_name)) {
        	$view_path = rtrim($this->view_dir, '/') . PATH . GET .ps('/view/',1). get('c', dt('c')) . '.' . Myuphp::os_config('html');
    	} else {
    		$view_path = rtrim($this->view_dir, '/') . $view_name;
		}
        //判断路径是否存在
        if (!file_exists($view_path)) {
            die($view_path.'模板文件不存在');
        }
        //通过传入的文件名得到缓存文件名
        $cache_name = md5($view_path . $uri) . '.php';
        //缓过缓存文件名得到缓存路径
        $cache_path = rtrim($this->cache_dir, '/') . 'data/cache/' . $cache_name;
        //判断缓存文件是否存在，如果不存在，重新生成
        if (!file_exists($cache_path)) {
            $php = $this->compile($view_path);
            //解析模板文件
            file_put_contents($cache_path, $php);
            //缓存文件重新生成
        } else {
            //如果缓存文件存在，判断是否过期，判断模板文件是否被修改
            $is_time_out = filectime($cache_path) + $this->lifetime > time() ? false : true;
            $is_change = filemtime($view_path) > filemtime($cache_path) ? true : false;
            //如果缓存文件过期或模板文件被修改，重新生成缓存文件
            if ($is_time_out || $is_change) {
                $php = $this->compile($view_path);
                file_put_contents($cache_path, $php);
            }
        }
        if ($isInclude) {
            extract($this->vars);
            //解析传入变量的数组
            include ps($cache_path,1);
            //展示缓存
        }
    }
    /**
     * 正则解析模板文件
     * @param string $file_name
     * @return mixed|string
     */
    protected function compile($file_name)
    {
        $html = file_get_contents($file_name);
        //获取模板文件
        //正则转换数组
        $array = [
        	'{:%%}' => '<?php echo \\1;?>', 
        	'{$%%.%%}' => "<?php echo $\\1['\\2'];?>", 
        	'{$%%}' => '<?php echo $\\1;?>', 
        	'{loop %%}' => '<?php foreach (\\1){ ?>',
        	'{/loop}' => '<?php } ?>', 
        	'{include %%}' => '<?php include \\1;?>', 
        	'{if %%}' => '<?php if (\\1){ ?>', 
        	'{else}' => '<?php } else { ?>', 
        	'{elseif %%}' => '<?php } elseif(\\1) { ?>', 
        	'{if}' => '<?php } ?>', 
        	'{/if}' => '<?php } ?>', 
        	'{%%(%%.%%)}' => "<?php echo \\1('\\2','\\3');?>", 
        ];
        //遍历数组，生成正则表达式
        foreach ($array as $key => $value) {
            //正则表达式，
            $pattern = '#' . str_replace('%%', '(.+?)', preg_quote($key, '#')) . '#';
            if (strstr($pattern, 'include')) {
                $html = preg_replace_callback($pattern, [$this, 'parseInclude'], $html);
            } else {
                $html = preg_replace($pattern, $value, $html);
            }
        }
        return $html;
    }
    /**
     * 处理include表达式
     * @param array $data
     * @return string
     */
    protected function parseInclude($data)
    {
        $file_name = trim($data[1], '\'"');
        $this->view($file_name, false);
        $cache_name = md5($file_name) . '.php';
        $cache_path = rtrim($this->cache_dir, '/') . 'data/cache/' . $cache_name;
        return '<?php include "' . $cache_path . '" ?>';
    }
    /**
     * 错误跳转
     * @param string $name
     * @param string $url
     */
    public function error($name, $url='')
    {
        $this->assign('name',$name);
        if (empty($url)) {
            if (isset($_SERVER['HTTP_REFERER'])) {
                $url= $_SERVER['HTTP_REFERER'];
            } else {
                $url= '/';
            }
        } 
        $this->assign('url',$url);
        $this->view('myuphp/Tpl/error.html');
        die();
    }
    /**
     * 成功跳转
     * @param string $name
     * @param string $url
     */
    public function success($name, $url='')
    {
        $this->assign('name',$name);
        if (empty($url)) {
            if (isset($_SERVER['HTTP_REFERER'])) {
                $url= $_SERVER['HTTP_REFERER'];
            } else {
                $url= '/';
            }
        } 
        $this->assign('url',$url);
        $this->view('myuphp/Tpl/success.html');
        die();
    }
}